package com.cnap.service.impl;

import cn.hutool.core.io.FileUtil;
import cn.hutool.core.util.IdUtil;
import com.cnap.CnapApplicationTests;
import com.cnap.config.DockerConfig;
import com.cnap.db.entity.ApplicationPO;
import com.cnap.db.entity.ClusterInfoPO;
import com.cnap.db.entity.MicroServicePO;
import com.cnap.db.entity.ProgressPO;
import com.cnap.db.entity.StrategyPO;
import com.cnap.db.mapper.MicroServiceMapper;
import com.cnap.db.mapper.StrategyMapper;
import com.cnap.model.application.ApplicationLabel;
import com.cnap.model.application.CategoryEnum;
import com.cnap.model.cloud.scaling.ScalingPolicyPO;
import com.cnap.model.cloud.scaling.UpdateScalingParam;
import com.cnap.model.common.PageResult;
import com.cnap.model.exception.JsonException;
import com.cnap.model.image.config.ConfigImageInfo;
import com.cnap.model.image.config.ConfigInfo;
import com.cnap.model.image.config.ConfigServiceInfo;
import com.cnap.model.progress.ProgressConstants;
import com.cnap.model.schedule.ClusterDetail;
import com.cnap.model.schedule.ClusterInfo;
import com.cnap.model.schedule.DistributeParam;
import com.cnap.model.schedule.MicroServiceVO;
import com.cnap.model.schedule.QueryMicroServiceParam;
import com.cnap.model.schedule.StrategyStatusEnum;
import com.cnap.model.schedule.StrategyTypeEnum;
import com.cnap.model.schedule.UpdateMicroServiceStatusParam;
import com.cnap.model.schedule.UpdateMicroserviceClusterParam;
import com.cnap.model.schedule.UpdateUserChooseParam;
import com.cnap.model.schedule.ValidateParam;
import com.cnap.model.schedule.engine.CommentResultForEngine;
import com.cnap.model.schedule.engine.DeployPolicyDistributeReq;
import com.cnap.model.schedule.engine.DeployPolicyValidateReq;
import com.cnap.model.schedule.engine.EngineClusterInfo;
import com.cnap.model.schedule.engine.ValidateResponse;
import com.cnap.service.AlgorithmEngineService;
import com.cnap.service.ApplicationService;
import com.cnap.service.CloudMgmtService;
import com.cnap.service.ClusterInfoService;
import com.cnap.service.DistributeDeployService;
import com.cnap.service.FileService;
import com.cnap.service.ProgressService;
import com.cnap.service.ScheduleService;
import com.cnap.utils.JsonUtil;
import com.fasterxml.jackson.core.type.TypeReference;
import com.github.dockerjava.api.DockerClient;
import com.github.dockerjava.api.command.LoadImageCmd;
import com.github.dockerjava.api.command.PushImageCmd;
import com.github.dockerjava.api.command.RemoveImageCmd;
import com.github.dockerjava.api.command.TagImageCmd;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
import org.mockito.Mockito;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.mock.mockito.MockBean;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.time.LocalDateTime;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;

/**
 * <类文件描述>
 *
 * @author xc
 **/
class MicroSvcServiceImplTest extends CnapApplicationTests {

    @Autowired
    private MicroSvcServiceImpl microSvcService;

    @Autowired
    private FileService fileService;
    @MockBean
    private StrategyMapper strategyMapperMock;
    @MockBean
    private MicroServiceMapper microServiceMapperMock;
    @MockBean
    private AlgorithmEngineService algorithmEngineServiceMock;
    @MockBean
    private ApplicationService applicationServiceMock;
    @MockBean
    private ClusterInfoService clusterInfoServiceMock;
    @MockBean
    private ProgressService progressServiceMock;
    @MockBean
    private DockerConfig dockerConfig;
    @MockBean
    private DistributeDeployService distributeDeployServiceMock;
    @MockBean
    private CloudMgmtService cloudMgmtServiceMock;
    @MockBean
    private ScheduleService scheduleServiceMock;


    @Test
    void splitMicroServicesWithNoApp() {
        Assertions.assertThrows(JsonException.class, () -> {
            microSvcService.splitMicroServices("appId");
        });
    }

    @Test
    void splitMicroServicesWithDupSplit() {
        ApplicationPO applicationPO = new ApplicationPO();
        applicationPO.setUserName("admin");
        Mockito.when(applicationServiceMock.selectByAppId("appId")).thenReturn(applicationPO);
        Mockito.when(microServiceMapperMock.selectMicroServiceByAppId("appId")).thenReturn(Collections.singletonList(new MicroServicePO()));

        microSvcService.splitMicroServices("appId");
        Assertions.assertTrue(true);
    }

    @Test
    void splitMicroServicesWithDupSplit2() {
        ApplicationPO applicationPO = new ApplicationPO();
        applicationPO.setUserName("admin");
        Mockito.when(applicationServiceMock.selectByAppId("appId")).thenReturn(applicationPO);
        Mockito.when(microServiceMapperMock.selectMicroServiceByAppId("appId")).thenReturn(Collections.emptyList());

        ProgressPO progressPO = new ProgressPO();
        progressPO.setType(ProgressConstants.TYPE_SPLIT);
        Mockito.when(progressServiceMock.getProgressPOByApplicationId("appId")).thenReturn(progressPO);

        microSvcService.splitMicroServices("appId");
        Assertions.assertTrue(true);
    }

    @Test
    void splitMicroServicesWithNoZipFile() {
        ApplicationPO applicationPO = new ApplicationPO();
        applicationPO.setUserName("admin");
        Mockito.when(applicationServiceMock.selectByAppId("appId")).thenReturn(applicationPO);
        Mockito.when(microServiceMapperMock.selectMicroServiceByAppId("appId")).thenReturn(Collections.emptyList());

        ProgressPO progressPO = new ProgressPO();
        progressPO.setType(ProgressConstants.TYPE_UPLOAD);
        Mockito.when(progressServiceMock.getProgressPOByApplicationId("appId")).thenReturn(progressPO);

        Assertions.assertThrows(JsonException.class, () -> {
            microSvcService.splitMicroServices("appId");
        });
    }

    @Test
    void splitMicroServices() throws IOException, InterruptedException {
        ApplicationPO applicationPO = new ApplicationPO();
        applicationPO.setUserName("admin");
        Mockito.when(applicationServiceMock.selectByAppId("appId")).thenReturn(applicationPO);
        Mockito.when(microServiceMapperMock.selectMicroServiceByAppId("appId")).thenReturn(Collections.emptyList());

        ProgressPO progressPO = new ProgressPO();
        progressPO.setType(ProgressConstants.TYPE_UPLOAD);
        Mockito.when(progressServiceMock.getProgressPOByApplicationId("appId")).thenReturn(progressPO);
        fileUtilMockedStatic.when(() -> {
            FileUtil.exist(Mockito.anyString());
        }).thenReturn(true);

        Mockito.when(progressServiceMock.updateProgress(Mockito.any(ProgressPO.class))).thenReturn(true);

        //Mockito.when(fileService.getSavePath("appId")).thenReturn("test-classes\\tmp\\appId");
        String configStr = "image=mask.tar\n" +
                "imageName=172.25.4.11/public/mask-detection-service:master-0803-d5f8565\n" +
                "imageMd5=202cb962ac59075b964b07152d234b70\n" +
                "path=/\n" +
                "framework=tensorflow\n" +
                "serviceName=安全帽检测\n" +
                "yaml=mask-detection-service.yaml";
        File f = new File(fileService.getSavePath("appId") + File.separator + "unzip" + File.separator + "1");
        if (!f.exists()) {
            f.mkdirs();
        }
        File tmpConfigFile = new File(fileService.getSavePath("appId") + File.separator + "unzip" + File.separator + "1" +
                File.separator + "config");
        tmpConfigFile.createNewFile();
        FileOutputStream fileOutputStream = new FileOutputStream(tmpConfigFile);
        fileOutputStream.write(configStr.getBytes(StandardCharsets.UTF_8));
        fileOutputStream.close();

        File imageTar = new File(fileService.getSavePath("appId") + File.separator + "unzip" + File.separator + "1" +
                File.separator + "mask.tar");
        // 202cb962ac59075b964b07152d234b70
        FileOutputStream fileOutputStream1 = new FileOutputStream(imageTar);
        fileOutputStream1.write("123".getBytes(StandardCharsets.UTF_8));

        DockerClient dockerClient = Mockito.mock(DockerClient.class);
        Mockito.when(dockerConfig.getDockerClient()).thenReturn(dockerClient);
        LoadImageCmd loadImageCmd = Mockito.mock(LoadImageCmd.class);
        Mockito.when(dockerClient.loadImageCmd(new FileInputStream(imageTar))).thenReturn(loadImageCmd);
        //Mockito.doNothing().when(loadImageCmd.exec());
        TagImageCmd tagImageCmd = Mockito.mock(TagImageCmd.class);
        Mockito.when(dockerClient.tagImageCmd(Mockito.anyString(), Mockito.anyString(), Mockito.anyString())).thenReturn(tagImageCmd);
        //Mockito.doNothing().when(tagImageCmd.exec());
        PushImageCmd pushImageCmd = Mockito.mock(PushImageCmd.class);
        Mockito.when(dockerClient.pushImageCmd(Mockito.anyString())).thenReturn(pushImageCmd);
        //Mockito.doNothing().when(pushImageCmd.start().awaitCompletion());
        RemoveImageCmd removeImageCmd = Mockito.mock(RemoveImageCmd.class);
        Mockito.when(dockerClient.removeImageCmd(Mockito.anyString())).thenReturn(removeImageCmd);
        //Mockito.doNothing().when(removeImageCmd.exec());


        Assertions.assertDoesNotThrow(() -> {
            microSvcService.splitMicroServices("appId");
            Thread.sleep(30000);
        });

        FileUtil.del("./tmp");

    }

    @Test
    void findByPage() {
        //Mockito.when(userServiceMock.checkUserHasAdminRole()).thenReturn(true);

        QueryMicroServiceParam queryMicroServiceParam = new QueryMicroServiceParam();
        queryMicroServiceParam.setPageNum(1);
        queryMicroServiceParam.setPageSize(10);

        MicroServicePO microServicePO = new MicroServicePO();
        microServicePO.setId(IdUtil.simpleUUID());
        microServicePO.setApplicationId("appId");
        microServicePO.setApplicationName("appName");
        microServicePO.setServiceName("svcName");
        microServicePO.setSize("400MB");
        microServicePO.setStatus(StrategyStatusEnum.INIT.getStatus());
        microServicePO.setUserName("admin");
        microServicePO.setPath("xxx/AI/1234234");
        microServicePO.setUpdateTime(LocalDateTime.now());
        Mockito.when(microServiceMapperMock.selectDeployedMicroServiceByParamWithUser(queryMicroServiceParam, "admin"))
                .thenReturn(Collections.singletonList(microServicePO));

        StrategyPO scheduleStrategy = new StrategyPO();
        ClusterInfo clusterInfo = new ClusterInfo();
        ClusterDetail clusterDetail = new ClusterDetail();
        clusterDetail.setClusterName("123");
        clusterDetail.setIp("1.1.1.1");
        ClusterDetail clusterDetail1 = new ClusterDetail();
        clusterDetail1.setClusterName("456");
        clusterDetail1.setIp("2.1.1.1");
        clusterInfo.setClusterNames(Arrays.asList("123", "456"));
        clusterInfo.setManufacturer("aliyun");
        //scheduleStrategy.setClusterInfos(Collections.singletonList(clusterInfo));
        scheduleStrategy.setStrategyParam("param");
        scheduleStrategy.setType(StrategyTypeEnum.SCHEDULE_STRATEGY.getValue());
        scheduleStrategy.setStrategyName("负载感知");
        scheduleStrategy.setEnableDefault(1);
        scheduleStrategy.setId(IdUtil.simpleUUID());
        Mockito.when(strategyMapperMock.selectStrategyByServiceIdAndType(microServicePO.getId(),
                StrategyTypeEnum.SCHEDULE_STRATEGY.getValue())).thenReturn(scheduleStrategy);
        StrategyPO scaleStrategy = new StrategyPO();

        //scaleStrategy.setClusterInfos(Collections.singletonList(clusterInfo));
        scaleStrategy.setStrategyParam("param2");
        scaleStrategy.setType(StrategyTypeEnum.SCALE_STRATEGY.getValue());
        scaleStrategy.setStrategyName("无");
        scaleStrategy.setEnableDefault(1);
        scaleStrategy.setId(IdUtil.simpleUUID());
        Mockito.when(strategyMapperMock.selectStrategyByServiceIdAndType(microServicePO.getId(),
                StrategyTypeEnum.SCALE_STRATEGY.getValue())).thenReturn(scaleStrategy);

        ClusterInfoPO clusterInfoPO = new ClusterInfoPO();
        EngineClusterInfo engineClusterInfo = new EngineClusterInfo();
        engineClusterInfo.setName("name");
        engineClusterInfo.setIp("ip");
        engineClusterInfo.setProviderName("aliyun");
        clusterInfoPO.setClusterInfos(Collections.singletonList(engineClusterInfo));
        clusterInfoPO.setUserChooseCloud("aliyun");

        Mockito.when(clusterInfoServiceMock.getClusterInfoBySvcId(microServicePO.getId())).thenReturn(clusterInfoPO);
        PageResult<MicroServiceVO> result = microSvcService.findByPage(queryMicroServiceParam);

        Assertions.assertEquals(1, result.getData().size());
    }

    @Test
    void deleteMicroServiceAndStrategyWithAppId() {
        MicroServicePO po = new MicroServicePO();
        po.setId("1");
        Mockito.when(microServiceMapperMock.selectMicroServiceByAppId("appId")).thenReturn(Collections.singletonList(po));
        Mockito.when(strategyMapperMock.deleteStrategyBySvcId("1")).thenReturn(1);
        Mockito.when(microServiceMapperMock.deleteMicroServiceByAppId("appId")).thenReturn(1);

        Assertions.assertDoesNotThrow(() -> {
            microSvcService.deleteMicroServiceAndStrategyWithAppId("appId");
        });
    }

    @Test
    void getYamlByServiceIdWithNull() {
        Mockito.when(microServiceMapperMock.selectMicroServiceById("svcId")).thenReturn(null);

        Assertions.assertThrows(JsonException.class, () -> {
            microSvcService.getYamlByServiceId("svcId");
        });
    }

    @Test
    void getYamlByServiceIdWithNoPermissions() {
        MicroServicePO microServicePO = new MicroServicePO();
        microServicePO.setUserName("xc");
        Mockito.when(microServiceMapperMock.selectMicroServiceById("svcId")).thenReturn(microServicePO);

        Assertions.assertThrows(JsonException.class, () -> {
            microSvcService.getYamlByServiceId("svcId");
        });
    }

    @Test
    void getYamlByServiceId() {
        MicroServicePO microServicePO = new MicroServicePO();
        microServicePO.setUserName("admin");
        microServicePO.setYaml("yaml");
        Mockito.when(microServiceMapperMock.selectMicroServiceById("svcId")).thenReturn(microServicePO);

        String yaml = microSvcService.getYamlByServiceId("svcId");

        Assertions.assertEquals("yaml", yaml);
    }

    @Test
    void validateWithNoMicroservice() {
        ValidateParam param = new ValidateParam();
        param.setServiceId("svcId");
        param.setClusters(Collections.singletonList("811"));

        Mockito.when(microServiceMapperMock.selectMicroServiceById("svcId")).thenReturn(null);

        Assertions.assertThrows(JsonException.class, () -> {
            microSvcService.validate(param);
        });
    }

    @Test
    void validateFail() {
        ValidateParam param = new ValidateParam();
        param.setServiceId("svcId");
        param.setClusters(Collections.singletonList("811"));

        MicroServicePO microServicePO = new MicroServicePO();
        microServicePO.setUserName("admin");
        Mockito.when(microServiceMapperMock.selectMicroServiceById("svcId")).thenReturn(microServicePO);

        String s = "{\n" +
                "    \"code\": 200,\n" +
                "    \"data\": {\n" +
                "        \"results\": [\n" +
                "            {\n" +
                "                \"pass\": false,\n" +
                "                \"desc\": \"验证失败!\",\n" +
                "                \"cluster\": \"cluster1\",\n" +
                "                \"detail\": \"端口占用\"\n" +
                "            },\n" +
                "            {\n" +
                "                \"pass\": true,\n" +
                "                \"desc\": \"验证通过\",\n" +
                "                \"cluster\": \"cluster2\",\n" +
                "                \"detail\": \"\"\n" +
                "            }\n" +
                "        ]\n" +
                "    },\n" +
                "    \"message\": \"执行成功\"\n" +
                "}";
        CommentResultForEngine<ValidateResponse> result = JsonUtil.jsonStrToObject(s,
                new TypeReference<CommentResultForEngine<ValidateResponse>>() {
                });
        Mockito.when(algorithmEngineServiceMock.validate(Mockito.any(DeployPolicyValidateReq.class))).thenReturn(result);
        Assertions.assertThrows(JsonException.class, () -> {
            microSvcService.validate(param);
        });
    }

    @Test
    void validateSuccess() {
        ValidateParam param = new ValidateParam();
        param.setServiceId("svcId");
        param.setClusters(Collections.singletonList("811"));

        MicroServicePO microServicePO = new MicroServicePO();
        microServicePO.setUserName("admin");
        Mockito.when(microServiceMapperMock.selectMicroServiceById("svcId")).thenReturn(microServicePO);

        String s = "{\n" +
                "    \"code\": 200,\n" +
                "    \"data\": {\n" +
                "        \"results\": [\n" +
                "            {\n" +
                "                \"pass\": true,\n" +
                "                \"desc\": \"验证失败!\",\n" +
                "                \"cluster\": \"cluster1\",\n" +
                "                \"detail\": \"端口占用\"\n" +
                "            },\n" +
                "            {\n" +
                "                \"pass\": true,\n" +
                "                \"desc\": \"验证通过\",\n" +
                "                \"cluster\": \"cluster2\",\n" +
                "                \"detail\": \"\"\n" +
                "            }\n" +
                "        ]\n" +
                "    },\n" +
                "    \"message\": \"执行成功\"\n" +
                "}";
        CommentResultForEngine<ValidateResponse> result = JsonUtil.jsonStrToObject(s,
                new TypeReference<CommentResultForEngine<ValidateResponse>>() {
                });
        Mockito.when(algorithmEngineServiceMock.validate(Mockito.any(DeployPolicyValidateReq.class))).thenReturn(result);
        boolean res = microSvcService.validate(param);
        Assertions.assertTrue(res);
    }

    @Test
    void selectMicroServicesByAppId() {
        MicroServicePO microServicePO = new MicroServicePO();
        microServicePO.setUserName("qwe");
        microServicePO.setId("svcId");
        microServicePO.setApplicationId("appId");
        microServicePO.setApplicationName("appName");
        microServicePO.setMicroServiceName("svcName");
        microServicePO.setSize("300MB");
        microServicePO.setStatus(1);
        microServicePO.setUserName("admin");
        microServicePO.setPath("/");
        microServicePO.setUpdateTime(LocalDateTime.now());
        microServicePO.setCategory(CategoryEnum.CATEGORY_AI.getValue());

        Mockito.when(microServiceMapperMock.selectMicroServiceByAppId("appId")).thenReturn(Collections.singletonList(microServicePO));

        StrategyPO schedule = new StrategyPO();
        schedule.setStrategyName("scheduleName");
        schedule.setStrategyParam("param");
        schedule.setId("scheduleId");
        schedule.setEnableDefault(1);
        ClusterInfo clusterInfo = new ClusterInfo();
        clusterInfo.setClusterNames(Arrays.asList("811", "32"));
        clusterInfo.setManufacturer("huaweiCloud");
        //schedule.setClusterInfos(Collections.singletonList(clusterInfo));

        Mockito.when(strategyMapperMock.selectStrategyByServiceIdAndType("svcId",
                StrategyTypeEnum.SCHEDULE_STRATEGY.getValue())).thenReturn(schedule);
        Mockito.when(strategyMapperMock.selectStrategyByServiceIdAndType("svcId",
                StrategyTypeEnum.SCALE_STRATEGY.getValue())).thenReturn(null);

        List<MicroServiceVO> vod = microSvcService.selectMicroServicesByAppId("appId");
        Assertions.assertEquals(1, vod.size());
    }

    @Test
    void selectMicroServicesByAppIdWithNoPermissions() {
        MicroServicePO microServicePO = new MicroServicePO();
        microServicePO.setUserName("qwe");
        microServicePO.setId("svcId");
        microServicePO.setApplicationId("appId");
        microServicePO.setApplicationName("appName");
        microServicePO.setMicroServiceName("svcName");
        microServicePO.setSize("300MB");
        microServicePO.setStatus(1);
        microServicePO.setUserName("zxc");
        microServicePO.setPath("/");
        microServicePO.setUpdateTime(LocalDateTime.now());
        microServicePO.setCategory(CategoryEnum.CATEGORY_AI.getValue());

        Mockito.when(microServiceMapperMock.selectMicroServiceByAppId("appId")).thenReturn(Collections.singletonList(microServicePO));

        StrategyPO schedule = new StrategyPO();
        schedule.setStrategyName("scheduleName");
        schedule.setStrategyParam("param");
        schedule.setId("scheduleId");
        schedule.setEnableDefault(1);
        ClusterInfo clusterInfo = new ClusterInfo();
        clusterInfo.setClusterNames(Arrays.asList("811", "32"));
        clusterInfo.setManufacturer("huaweiCloud");
        //schedule.setClusterInfos(Collections.singletonList(clusterInfo));

        Mockito.when(strategyMapperMock.selectStrategyByServiceIdAndType("svcId",
                StrategyTypeEnum.SCHEDULE_STRATEGY.getValue())).thenReturn(schedule);
        Mockito.when(strategyMapperMock.selectStrategyByServiceIdAndType("svcId",
                StrategyTypeEnum.SCALE_STRATEGY.getValue())).thenReturn(null);

        Assertions.assertThrows(JsonException.class, () -> {
            microSvcService.selectMicroServicesByAppId("appId");
        });
    }

    @Test
    void distributeWithNoMicroservice() {
        DistributeParam param = new DistributeParam();
        param.setServiceId("svcId");
        param.setClusters(Collections.singletonList("811"));
        param.setYaml("yaml");

        Mockito.when(microServiceMapperMock.selectMicroServiceById("svcId")).thenReturn(null);


        Assertions.assertThrows(JsonException.class, () -> {
            microSvcService.distribute(param);
        });
    }

    @Test
    void distributeWithNoPermissions() {
        DistributeParam param = new DistributeParam();
        param.setServiceId("svcId");
        param.setClusters(Collections.singletonList("811"));
        param.setYaml("yaml");

        MicroServicePO microServicePO = new MicroServicePO();
        microServicePO.setUserName("asd");
        Mockito.when(microServiceMapperMock.selectMicroServiceById("svcId")).thenReturn(microServicePO);


        Assertions.assertThrows(JsonException.class, () -> {
            microSvcService.distribute(param);
        });
    }

    @Test
    void distributeWithNoStrategy() {
        DistributeParam param = new DistributeParam();
        param.setServiceId("svcId");
        param.setClusters(Collections.singletonList("811"));
        param.setYaml("yaml");

        MicroServicePO microServicePO = new MicroServicePO();
        microServicePO.setUserName("admin");
        Mockito.when(microServiceMapperMock.selectMicroServiceById("svcId")).thenReturn(microServicePO);


        Assertions.assertThrows(JsonException.class, () -> {
            microSvcService.distribute(param);
        });
    }

    @Test
    void distributeWithFail() {
        DistributeParam param = new DistributeParam();
        param.setServiceId("svcId");
        param.setClusters(Collections.singletonList("811"));
        param.setYaml("yaml");

        MicroServicePO microServicePO = new MicroServicePO();
        microServicePO.setUserName("admin");
        microServicePO.setYaml("yaml");
        microServicePO.setPath("/asda/");
        microServicePO.setCategory(CategoryEnum.CATEGORY_AI.getValue());
        microServicePO.setFramework("pytorch");
        microServicePO.setApplicationId("appId");
        Mockito.when(microServiceMapperMock.selectMicroServiceById("svcId")).thenReturn(microServicePO);

        StrategyPO schedule = new StrategyPO();
        schedule.setStrategyParam("param");
        Mockito.when(strategyMapperMock.selectStrategyByServiceIdAndType("svcId",
                StrategyTypeEnum.SCHEDULE_STRATEGY.getValue())).thenReturn(schedule);
        StrategyPO scale = new StrategyPO();
        scale.setStrategyParam("param12");
        Mockito.when(strategyMapperMock.selectStrategyByServiceIdAndType("svcId",
                StrategyTypeEnum.SCALE_STRATEGY.getValue())).thenReturn(scale);

        ApplicationPO applicationPO = new ApplicationPO();
        ApplicationLabel label = new ApplicationLabel();
        label.setTechnology(Collections.singletonList("12"));
        label.setObjectScene(Collections.singletonList("34"));
        Mockito.when(applicationServiceMock.selectByAppId("appId")).thenReturn(applicationPO);

        applicationPO.setLabel(label);

        String s = "{\n" +
                "  \"code\": 200,\n" +
                "  \"data\": {\n" +
                "    \"results\": [\n" +
                "      {\n" +
                "        \"pass\": false,\n" +
                "        \"desc\": \"部署失败!\",\n" +
                "        \"cluster\": \"cluster1\",\n" +
                "        \"detail\": \"端口占用\"\n" +
                "      },\n" +
                "      {\n" +
                "        \"pass\": true,\n" +
                "        \"desc\": \"部署成功\",\n" +
                "        \"cluster\": \"cluster2\",\n" +
                "        \"detail\": \"\"\n" +
                "      }\n" +
                "    ]\n" +
                "  },\n" +
                "  \"message\": \"执行成功\"\n" +
                "}";
        CommentResultForEngine<ValidateResponse> result = JsonUtil.jsonStrToObject(s,
                new TypeReference<CommentResultForEngine<ValidateResponse>>() {
                });
        Mockito.when(algorithmEngineServiceMock.distribute(Mockito.any(DeployPolicyDistributeReq.class))).thenReturn(result);
        Assertions.assertThrows(JsonException.class, () -> {
            microSvcService.distribute(param);
        });
    }

    @Test
    void distribute() {
        DistributeParam param = new DistributeParam();
        param.setServiceId("svcId");
        param.setClusters(Collections.singletonList("811"));
        param.setYaml("yaml");

        MicroServicePO microServicePO = new MicroServicePO();
        microServicePO.setUserName("admin");
        microServicePO.setYaml("yaml");
        microServicePO.setPath("/asda/");
        microServicePO.setCategory(CategoryEnum.CATEGORY_AI.getValue());
        microServicePO.setFramework("pytorch");
        microServicePO.setApplicationId("appId");
        Mockito.when(microServiceMapperMock.selectMicroServiceById("svcId")).thenReturn(microServicePO);

        StrategyPO schedule = new StrategyPO();
        schedule.setStrategyParam("param");
        Mockito.when(strategyMapperMock.selectStrategyByServiceIdAndType("svcId",
                StrategyTypeEnum.SCHEDULE_STRATEGY.getValue())).thenReturn(schedule);
        StrategyPO scale = new StrategyPO();
        scale.setStrategyParam("param12");
        Mockito.when(strategyMapperMock.selectStrategyByServiceIdAndType("svcId",
                StrategyTypeEnum.SCALE_STRATEGY.getValue())).thenReturn(scale);

        ApplicationPO applicationPO = new ApplicationPO();
        ApplicationLabel label = new ApplicationLabel();
        label.setTechnology(Collections.singletonList("12"));
        label.setObjectScene(Collections.singletonList("34"));
        Mockito.when(applicationServiceMock.selectByAppId("appId")).thenReturn(applicationPO);

        applicationPO.setLabel(label);

        String s = "{\n" +
                "  \"code\": 200,\n" +
                "  \"data\": {\n" +
                "    \"results\": [\n" +
                "      {\n" +
                "        \"pass\": true,\n" +
                "        \"desc\": \"部署失败!\",\n" +
                "        \"cluster\": \"cluster1\",\n" +
                "        \"detail\": \"端口占用\"\n" +
                "      },\n" +
                "      {\n" +
                "        \"pass\": true,\n" +
                "        \"desc\": \"部署成功\",\n" +
                "        \"cluster\": \"cluster2\",\n" +
                "        \"detail\": \"\"\n" +
                "      }\n" +
                "    ]\n" +
                "  },\n" +
                "  \"message\": \"执行成功\"\n" +
                "}";
        CommentResultForEngine<ValidateResponse> result = JsonUtil.jsonStrToObject(s,
                new TypeReference<CommentResultForEngine<ValidateResponse>>() {
                });
        Mockito.when(algorithmEngineServiceMock.distribute(Mockito.any(DeployPolicyDistributeReq.class))).thenReturn(result);

        Mockito.when(microServiceMapperMock.selectMicroServiceByAppId("appId")).thenReturn(Collections.emptyList());

        EngineClusterInfo engineClusterInfo = new EngineClusterInfo();
        engineClusterInfo.setIp("1.1.1.1");
        engineClusterInfo.setInnerIp("2.2.2.2");
        engineClusterInfo.setProviderName("Huawei");
        schedule.setClusterInfos(Collections.singletonList(engineClusterInfo));

        ClusterInfoPO clusterInfoPO = new ClusterInfoPO();
        clusterInfoPO.setUserChooseCloud("Huawei");
        Mockito.when(clusterInfoServiceMock.getClusterInfoBySvcId("svcId")).thenReturn(clusterInfoPO);
        Mockito.when(strategyMapperMock.updateStrategy(schedule)).thenReturn(1);


        Assertions.assertDoesNotThrow(() -> {
            microSvcService.distribute(param);
        });
    }

    @Test
    void updateMicroServiceStatusWithNoMicroservice() {
        UpdateMicroServiceStatusParam param = new UpdateMicroServiceStatusParam();
        param.setId("svcId");
        param.setStatus("2");

        Assertions.assertThrows(JsonException.class, () -> {
            microSvcService.updateMicroServiceStatus(param);
        });
    }

    @Test
    void updateMicroServiceStatus() {
        UpdateMicroServiceStatusParam param = new UpdateMicroServiceStatusParam();
        param.setId("svcId");
        param.setStatus("6");

        MicroServicePO microServicePO = new MicroServicePO();
        microServicePO.setApplicationId("appId");
        Mockito.when(microServiceMapperMock.selectMicroServiceById("svcId")).thenReturn(microServicePO);
        Mockito.when(microServiceMapperMock.updateMicroServiceStatus("svcId", 0)).thenReturn(1);

        boolean result = microSvcService.updateMicroServiceStatus(param);

        Assertions.assertTrue(result);
    }

    @Test
    void updateMicroServiceStatusWithApplied() {
        UpdateMicroServiceStatusParam param = new UpdateMicroServiceStatusParam();
        param.setId("svcId");
        param.setStatus("1");

        MicroServicePO microServicePO = new MicroServicePO();
        microServicePO.setApplicationId("appId");
        Mockito.when(microServiceMapperMock.selectMicroServiceById("svcId")).thenReturn(microServicePO);
        Mockito.when(microServiceMapperMock.updateMicroServiceStatus("svcId", 0)).thenReturn(1);
        //DistributeDeployService distributeDeployService = Mockito.mock(DistributeDeployService.class);

        //spingUtilMockedStatic.when(() -> SpringUtil.getBean(DistributeDeployService.class)).thenReturn(distributeDeployService);

        //Mockito.when(distributeDeployService.updateStage(Mockito.any(UpdateStageParam.class))).thenReturn(true);
        Mockito.when(microServiceMapperMock.updateMicroServiceStatus(Mockito.eq("svcId"), Mockito.anyInt())).thenReturn(1);


        boolean result = microSvcService.updateMicroServiceStatus(param);

        Assertions.assertTrue(result);
    }

    @Test
    void updateMicroServiceStatusWithFail() {
        UpdateMicroServiceStatusParam param = new UpdateMicroServiceStatusParam();
        param.setId("svcId");
        param.setStatus("6");

        MicroServicePO microServicePO = new MicroServicePO();
        microServicePO.setApplicationId("appId");
        Mockito.when(microServiceMapperMock.selectMicroServiceById("svcId")).thenReturn(microServicePO);

        Mockito.when(microServiceMapperMock.updateMicroServiceStatus("svcId", Integer.parseInt(param.getStatus()))).thenReturn(0);

        boolean result = microSvcService.updateMicroServiceStatus(param);

        Assertions.assertFalse(result);
    }

    @Test
    void deleteMicroServiceImagesWithAppIdWithNoMicroservice() {
        boolean result = microSvcService.deleteMicroServiceImagesWithAppId("appId");
        Assertions.assertTrue(result);
    }

    @Test
    void getMicroserviceBySvcId() {
        Assertions.assertDoesNotThrow(() -> {
            microSvcService.getMicroserviceBySvcId("svcId");
        });
    }

    @Test
    void updateClusterInfo() {
        UpdateMicroserviceClusterParam param = new UpdateMicroserviceClusterParam();
        param.setSvcId("svcId");
        param.setClusterInfos(Collections.emptyList());
        Mockito.when(strategyMapperMock.selectStrategyByServiceIdAndType("svcId",
                StrategyTypeEnum.SCHEDULE_STRATEGY.getValue())).thenReturn(new StrategyPO());
        Mockito.when(strategyMapperMock.selectStrategyByServiceIdAndType("svcId",
                StrategyTypeEnum.SCALE_STRATEGY.getValue())).thenReturn(new StrategyPO());
        MicroServicePO po = new MicroServicePO();
        Mockito.when(microServiceMapperMock.selectMicroServiceById("svcId")).thenReturn(po);
        Mockito.doNothing().when(clusterInfoServiceMock).saveOrUpdateClusterInfo(po, param.getClusterInfos());

        boolean result = microSvcService.updateClusterInfo(param);
        Assertions.assertTrue(result);
    }

    @Test
    void testSaveMicroService() throws IOException {
        String yamlString = "---\n" +
                "apiVersion: \"v1\"\n" +
                "kind: \"Service\"\n" +
                "metadata:\n" +
                "  name: \"social1-service\"\n" +
                "  namespace: \"app-c508effe7d022befb214991bfdbbb8fd\"\n" +
                "spec:\n" +
                "  ports:\n" +
                "  - nodePort: 32513\n" +
                "    port: 8523\n" +
                "    protocol: \"TCP\"\n" +
                "    targetPort: 8523\n" +
                "  selector:\n" +
                "    app: \"social1\"\n" +
                "  type: \"NodePort\"\n" +
                "---\n" +
                "apiVersion: \"apps/v1\"\n" +
                "kind: \"Deployment\"\n" +
                "metadata:\n" +
                "  labels:\n" +
                "    app: \"social1\"\n" +
                "  name: \"social1\"\n" +
                "  namespace: \"app-c508effe7d022befb214991bfdbbb8fd\"\n" +
                "spec:\n" +
                "  progressDeadlineSeconds: 600\n" +
                "  replicas: 1\n" +
                "  revisionHistoryLimit: 10\n" +
                "  selector:\n" +
                "    matchLabels:\n" +
                "      app: \"social1\"\n" +
                "  strategy:\n" +
                "    rollingUpdate:\n" +
                "      maxSurge: 1\n" +
                "      maxUnavailable: 1\n" +
                "    type: \"RollingUpdate\"\n" +
                "  template:\n" +
                "    metadata:\n" +
                "      labels:\n" +
                "        app: \"social1\"\n" +
                "    spec:\n" +
                "      containers:\n" +
                "      - image: \"192.168.0.146/test/yuxiaolong1/social1:1.0\"\n" +
                "        imagePullPolicy: \"IfNotPresent\"\n" +
                "        name: \"social1\"\n" +
                "        ports:\n" +
                "        - containerPort: 8523\n" +
                "        resources:\n" +
                "          requests:\n" +
                "            cpu: \"50m\"\n" +
                "            memory: \"200Mi\"\n" +
                "      dnsPolicy: \"ClusterFirst\"\n" +
                "      restartPolicy: \"Always\"\n" +
                "      schedulerName: \"default-scheduler\"\n" +
                "      securityContext: {}\n" +
                "      terminationGracePeriodSeconds: 30\n";

        File f = new File(fileService.getSavePath("appId") + File.separator + "unzip" + File.separator + "1");
        if (!f.exists()) {
            f.mkdirs();
        }
        File tmpYamlFile = new File(fileService.getSavePath("appId") + File.separator + "unzip" + File.separator + "1" +
                File.separator + "yaml");
        tmpYamlFile.createNewFile();
        FileOutputStream fileOutputStream = new FileOutputStream(tmpYamlFile);
        fileOutputStream.write(yamlString.getBytes(StandardCharsets.UTF_8));
        fileOutputStream.close();

        ApplicationPO applicationPO = new ApplicationPO();
        applicationPO.setId("appId");
        applicationPO.setName("app-name");
        applicationPO.setUserName("userName");
        Mockito.when(applicationServiceMock.selectByAppId("appId")).thenReturn(applicationPO);

        ConfigInfo configInfo = new ConfigInfo();
        ConfigServiceInfo configServiceInfo = new ConfigServiceInfo();
        configServiceInfo.setServiceName("service-name");
        configServiceInfo.setFramework("pytorch");
        configServiceInfo.setPath(Collections.singletonList("/"));
        configInfo.setConfigServiceInfo(configServiceInfo);
        ConfigImageInfo configImageInfo = new ConfigImageInfo();
        configImageInfo.setImageName("192.168.0.146/test/yuxiaolong1/social1:1.0");
        configInfo.setConfigImageInfo(configImageInfo);

        Mockito.when(dockerConfig.getRegistryPrefix()).thenReturn("prefix");

        microSvcService.saveMicroService("appId", configInfo, tmpYamlFile.getAbsolutePath(), 100);

    }

    @Test
    void updateScalingPolicyTestWithEmpty() {
        UpdateScalingParam updateScalingParam = new UpdateScalingParam();
        updateScalingParam.setClusterName("clusterName");
        updateScalingParam.setProvider("Huawei");

        String userChooseCloud = "Huawei";
        ClusterInfoPO clusterInfoPO = new ClusterInfoPO();
        EngineClusterInfo engineClusterInfo = new EngineClusterInfo();
        engineClusterInfo.setName("clusterName1");
        engineClusterInfo.setProviderName("Huawei");
        clusterInfoPO.setClusterInfos(Collections.singletonList(engineClusterInfo));


        Mockito.when(clusterInfoServiceMock.getClusterInfoByUserChooseCloud(userChooseCloud))
                .thenReturn(Collections.singletonList(clusterInfoPO));

        Assertions.assertDoesNotThrow(()->{
            microSvcService.updateScalingPolicy(updateScalingParam);
        });

    }
    @Test
    void updateScalingPolicyTestWithStrateegyNull() {
        UpdateScalingParam updateScalingParam = new UpdateScalingParam();
        updateScalingParam.setClusterName("clusterName");
        updateScalingParam.setProvider("Huawei");

        String userChooseCloud = "Huawei";
        ClusterInfoPO clusterInfoPO = new ClusterInfoPO();
        clusterInfoPO.setId("svcId");
        EngineClusterInfo engineClusterInfo = new EngineClusterInfo();
        engineClusterInfo.setName("clusterName");
        engineClusterInfo.setProviderName("Huawei");
        clusterInfoPO.setClusterInfos(Collections.singletonList(engineClusterInfo));


        Mockito.when(clusterInfoServiceMock.getClusterInfoByUserChooseCloud(userChooseCloud))
                .thenReturn(Collections.singletonList(clusterInfoPO));

        Mockito.when(strategyMapperMock.selectVmScaleByServiceId("svcId")).thenReturn(null);

        Assertions.assertDoesNotThrow(()->{
            microSvcService.updateScalingPolicy(updateScalingParam);
        });
    }

    @Test
    void updateScalingPolicyTestWithNone() {
        UpdateScalingParam updateScalingParam = new UpdateScalingParam();
        updateScalingParam.setClusterName("clusterName");
        updateScalingParam.setProvider("Huawei");
        updateScalingParam.setScalingPolicyPOS(null);
        updateScalingParam.setCategory("AI");

        String userChooseCloud = "Huawei";
        ClusterInfoPO clusterInfoPO = new ClusterInfoPO();
        clusterInfoPO.setId("svcId");
        EngineClusterInfo engineClusterInfo = new EngineClusterInfo();
        engineClusterInfo.setName("clusterName");
        engineClusterInfo.setProviderName("Huawei");
        clusterInfoPO.setClusterInfos(Collections.singletonList(engineClusterInfo));

        MicroServicePO microServicePO = new MicroServicePO();
        microServicePO.setCategory("AI");
        Mockito.when(microServiceMapperMock.selectMicroServiceById("svcId")).thenReturn(microServicePO);

        Mockito.when(clusterInfoServiceMock.getClusterInfoByUserChooseCloud(userChooseCloud))
                .thenReturn(Collections.singletonList(clusterInfoPO));

        StrategyPO strategyPO = new StrategyPO();
        Mockito.when(strategyMapperMock.selectVmScaleByServiceId("svcId")).thenReturn(strategyPO);

        Mockito.when(strategyMapperMock.updateStrategy(Mockito.any())).thenReturn(1);

        Assertions.assertDoesNotThrow(()->{
            microSvcService.updateScalingPolicy(updateScalingParam);
        });
    }
    @Test
    void updateScalingPolicyTest() {
        UpdateScalingParam updateScalingParam = new UpdateScalingParam();
        updateScalingParam.setCategory("AI");
        updateScalingParam.setClusterName("clusterName");
        updateScalingParam.setProvider("Huawei");
        ScalingPolicyPO scalingPolicyPO = new ScalingPolicyPO();
        updateScalingParam.setScalingPolicyPOS(Collections.singletonList(scalingPolicyPO));

        String userChooseCloud = "Huawei";
        ClusterInfoPO clusterInfoPO = new ClusterInfoPO();
        clusterInfoPO.setId("svcId");
        EngineClusterInfo engineClusterInfo = new EngineClusterInfo();
        engineClusterInfo.setName("clusterName");
        engineClusterInfo.setProviderName("Huawei");
        clusterInfoPO.setClusterInfos(Collections.singletonList(engineClusterInfo));

        MicroServicePO microServicePO = new MicroServicePO();
        microServicePO.setCategory("AI");
        Mockito.when(microServiceMapperMock.selectMicroServiceById("svcId")).thenReturn(microServicePO);

        Mockito.when(clusterInfoServiceMock.getClusterInfoByUserChooseCloud(userChooseCloud))
                .thenReturn(Collections.singletonList(clusterInfoPO));

        StrategyPO strategyPO = new StrategyPO();
        Mockito.when(strategyMapperMock.selectVmScaleByServiceId("svcId")).thenReturn(strategyPO);

        Mockito.when(strategyMapperMock.updateStrategy(Mockito.any())).thenReturn(1);

        Assertions.assertDoesNotThrow(()->{
            microSvcService.updateScalingPolicy(updateScalingParam);
        });
    }

    @Test
    void updateUserChooseTestWithNoMicroservice() {
        UpdateUserChooseParam param = new UpdateUserChooseParam();
        param.setSvcId("svcId");

        Mockito.when(microServiceMapperMock.selectMicroServiceById("svcId")).thenReturn(null);

        Assertions.assertThrows(JsonException.class, ()->{
            microSvcService.updateUserChooseCloud(param);
        });
    }

    @Test
    void updateUserChooseTestWithNoStrategy() {
        UpdateUserChooseParam param = new UpdateUserChooseParam();
        param.setSvcId("svcId");

        Mockito.when(microServiceMapperMock.selectMicroServiceById("svcId")).thenReturn(new MicroServicePO());

        Mockito.when(strategyMapperMock.selectStrategyByServiceIdAndType("svcId",
                StrategyTypeEnum.SCHEDULE_STRATEGY.getValue())).thenReturn(null);
        Assertions.assertThrows(JsonException.class, ()->{
            microSvcService.updateUserChooseCloud(param);
        });
    }

    @Test
    void updateUserChooseTest() {
        UpdateUserChooseParam param = new UpdateUserChooseParam();
        param.setSvcId("svcId");

        Mockito.when(microServiceMapperMock.selectMicroServiceById("svcId")).thenReturn(new MicroServicePO());

        Mockito.when(strategyMapperMock.selectStrategyByServiceIdAndType("svcId",
                StrategyTypeEnum.SCHEDULE_STRATEGY.getValue())).thenReturn(new StrategyPO());
        Mockito.doNothing().when(clusterInfoServiceMock).updateUserChooseCloud(param);
        Assertions.assertDoesNotThrow(()->{
            microSvcService.updateUserChooseCloud(param);
        });
    }
}